热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

几何体|可能会_✿3TheBasics使用QtWidgets进行GUI设计

篇首语:本文由编程笔记#小编为大家整理,主要介绍了✿3-TheBasics-使用QtWidgets进行GUI设计相关的知识,希望对你有一定的参考价值。目录

篇首语:本文由编程笔记#小编为大家整理,主要介绍了✿3-The Basics-使用Qt Widgets进行GUI设计相关的知识,希望对你有一定的参考价值。



目录


      • 介绍Qt widgets
      • 使用Qt Designer创建UI
      • 管理布局
      • 创建自定义部件
      • 创建Qt样式表和自定义主题
        • 使用QSS文件
        • 探索自定义样式
          • 创建自定义样式
          • 使用自定义样式

        • 使用小部件、窗口和对话框

      • 总结




Qt Widgets是一个模块,它提供了一组用于构建经典UI的用户界面(UI)元素。在本章中,你将了解
Qt Widgets模块,并了解基本小部件。我们将了解什么是小部件,以及可用于创建图形用户界面(GUI)的各种小部件。除此之外,还将向你介绍
Qt Designer的布局,并学习如何创建自己的自定义控件。我们将仔细研究Qt在轻松设计外观光滑的GUI时能为我们提供什么。在本章的开头,你将了解Qt提供的小部件类型及其功能。之后,我们将完成一系列步骤,并使用Qt设计我们的第一个表单应用程序。然后,你将学习样式表、Qt样式表(
Qt Style Sheets)(QSS文件)和主题化。

本章将介绍以下主要主题:


  • 介绍Qt小部件
  • 使用Qt Designer创建UI
  • 管理布局
  • 创建自定义小部件
  • 创建Qt样式表和自定义主题
  • 探索自定义样式
  • 使用小部件、窗口和对话框

本章结束时,你将了解GUI元素及其相应的C++类的基础知识,如何在不编写一行代码的情况下创建自己的UI,以及如何使用样式表自定义UI的外观。


介绍Qt widgets

widget(小部件)是GUI的基本元素,它也被称为UI控件。它从底层平台接受不同的用户事件,例如鼠标和键盘事件(以及其他事件)。我们使用不同的小部件创建UI。曾经有一段时间,所有GUI控件都是从头开始编写的。Qt小部件通过开发带有现成GUI控件的桌面GUI来减少时间,Qt广泛使用继承的概念。所有小部件都继承自QObjectQWidget是一个基本的小部件,是所有UI小部件的基类;它包含描述小部件所需的大多数属性,以及几何体、颜色、鼠标、键盘行为、工具提示等属性。让我们看看下图中的QWidget继承层次结构:


  • QPushButton 用于命令应用程序执行特定操作。
  • QCheckBox 允许用户进行二进制选择。
  • QRadioButton 允许用户从一组相互排斥的选项中仅做出一个选择。
  • QFrame 显示一个框架。
  • QLabel 用于显示文本或图像。
  • QLineEdit 允许用户输入和编辑单行纯文本。
  • QTabWidget 用于在选项卡式窗口小部件的堆栈中显示与每个选项卡相关的页面。

使用Qt小部件的优点之一是它的继承系统。从QObject继承的任何对象都具有父子关系。这种关系为开发人员提供了许多便利,例如:


  • 当一个小部件被销毁时,由于父子层次结构,它的所有子部件也已经被销毁了。这样可以避免内存泄漏。
  • 通过使用findChild()findChildren()可以找到给定QWidget类的子类。
  • Qwidget中的子部件会自动出现在父部件中。

典型的C++程序在主main()函数返回时终止,但在GUI应用程序中,我们不能这样做,或者应用程序将无法使用。因此,我们需要GUI一直存在,直到用户关闭窗口。为了实现这一点,程序应该在循环中运行,直到发生这种情况。GUI应用程序等待用户输入事件。

让我们使用简单的GUI程序,使用QLabel显示一段文本:

#include
#include
int main(int argc, char *argv[])
QApplication app(argc, argv);
QLabel myLabel;
myLabel.setText("Hello World!");
myLabel.show();
return app.exec();

记住在.pro文件中添加以下行,用于启用Qt Widgets模块:

QT += widgets


使用Qt Designer创建UI


Qt Widgets模块附带了现成的小部件。Qt提供了一个通过拖放方法创建UI的选项。让我们通过简单地将这些小部件从小部件框区域拖动到表单编辑器区域来探索它们。在项目到达表单编辑器区域之前,不要释放鼠标或触控板。下面的屏幕截图显示了小部件框部分中可用的不同类型的小部件。我们在表单编辑器区域中添加了一些现成的小部件,如标签、按钮、单选按钮、复选框、组合框、进度条和行编辑。这些小部件是非常常用的小部件。你可以在 [属性编辑器] 中浏览特定于小部件的属性。

你可以预览UI:Tools->Form Editor->Preview

还可以查看UI对应的C++代码:Tools->C+±>Inspect C++ Code Model…


管理布局

Qt提供了一组方便的布局管理类,可以在另一个小部件中自动排列子小部件,以确保UI保持可用。QLayout类是所有布局管理器的基类。还可以通过重新实现setGeometry()、sizeHint()、addItem()、itemAt()、takeAt()和minimumSize()函数来创建自己的布局管理器。请注意,一旦删除布局管理器,布局管理也将停止。以下列表简要介绍了主要布局类:


  • QVBoxLayout 垂直排列小部件。
  • QHBoxLayout 水平排列小部件。
  • QGridLayout 在网格中布局小部件。
  • QFormLayout 管理各种形式的输入小部件及其相关标签。
  • QStackedLayout 提供了一组小部件,一次只能看到一个小部件。

QLayout通过从QObject和QLayoutItem继承来使用多个继承。QLayout的子类是QBoxLayout、QGridLayout、QFormLayout和QStackedLayout。QVBoxLayout和QHBoxLayout继承自QBoxLayout,并添加了方向信息。让我们使用Qt Designer模块来布置几个QPushButtons。

QVBoxLayout:

对应的完整C++代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
QT_BEGIN_NAMESPACE
class Ui_MainWindow
public:
QWidget *centralWidget;
QVBoxLayout *verticalLayout;
QPushButton *pushButton;
QPushButton *pushButton_2;
QPushButton *pushButton_3;
QPushButton *pushButton_4;
QMenuBar *menuBar;
QToolBar *mainToolBar;
QStatusBar *statusBar;
void setupUi(QMainWindow *MainWindow)
if (MainWindow->objectName().isEmpty())
MainWindow->setObjectName(QStringLiteral("MainWindow"));
MainWindow->resize(378, 282);
centralWidget = new QWidget(MainWindow);
centralWidget->setObjectName(QStringLiteral("centralWidget"));
verticalLayout = new QVBoxLayout(centralWidget);
verticalLayout->setSpacing(6);
verticalLayout->setContentsMargins(11, 11, 11, 11);
verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
pushButton = new QPushButton(centralWidget);
pushButton->setObjectName(QStringLiteral("pushButton"));
verticalLayout->addWidget(pushButton);
pushButton_2 = new QPushButton(centralWidget);
pushButton_2->setObjectName(QStringLiteral("pushButton_2"));
pushButton_2->setMinimumSize(QSize(366, 15));
verticalLayout->addWidget(pushButton_2);
pushButton_3 = new QPushButton(centralWidget);
pushButton_3->setObjectName(QStringLiteral("pushButton_3"));
verticalLayout->addWidget(pushButton_3);
pushButton_4 = new QPushButton(centralWidget);
pushButton_4->setObjectName(QStringLiteral("pushButton_4"));
verticalLayout->addWidget(pushButton_4);
MainWindow->setCentralWidget(centralWidget);
menuBar = new QMenuBar(MainWindow);
menuBar->setObjectName(QStringLiteral("menuBar"));
menuBar->setGeometry(QRect(0, 0, 378, 17));
MainWindow->setMenuBar(menuBar);
mainToolBar = new QToolBar(MainWindow);
mainToolBar->setObjectName(QStringLiteral("mainToolBar"));
MainWindow->addToolBar(Qt::TopToolBarArea, mainToolBar);
statusBar = new QStatusBar(MainWindow);
statusBar->setObjectName(QStringLiteral("statusBar"));
MainWindow->setStatusBar(statusBar);
retranslateUi(MainWindow);
QMetaObject::connectSlotsByName(MainWindow);
// setupUi
void retranslateUi(QMainWindow *MainWindow)
MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", Q_NULLPTR));
pushButton->setText(QApplication::translate("MainWindow", "PushButton1", Q_NULLPTR));
pushButton_2->setText(QApplication::translate("MainWindow", "PushButton2", Q_NULLPTR));
pushButton_3->setText(QApplication::translate("MainWindow", "PushButton3", Q_NULLPTR));
pushButton_4->setText(QApplication::translate("MainWindow", "PushButton4", Q_NULLPTR));
// retranslateUi
;
namespace Ui
class MainWindow: public Ui_MainWindow ;
// namespace Ui
QT_END_NAMESPACE

这个程序演示了如何使用垂直布局对象。请注意,QWidget实例widget将成为应用程序的主窗口。在这里,布局被直接设置为顶层布局。添加到addWidget()方法的第一个按钮占据版面的顶部,而最后一个按钮占据版面的底部。
如果没有在QWidget构造函数中设置父窗口,那么以后必须使用QWidget::setLayout()安装布局并重新分配到小部件实例。

QGridLayout:
你还可以通过C++代码动态添加网格布局,如下面的代码片段所示:

QWidget *widget = new QWidget;
QPushButton *pushBtn1 = new QPushButton( "Push Button 1");
QPushButton *pushBtn2 = new QPushButton( "Push Button 2");
QPushButton *pushBtn3 = new QPushButton( "Push Button 3");
QPushButton *pushBtn4 = new QPushButton( "Push Button 4");
QGridLayout *gridLayout = new QGridLayout(widget);
gridLayout->addWidget(pushBtn1);
gridLayout->addWidget(pushBtn2);
gridLayout->addWidget(pushBtn3);
gridLayout->addWidget(pushBtn4);
widget->show();

创建自定义部件

自定义小部件可以是一个或多个放置在一起的Qt小部件的组合,也可以从头开始编写。我们将从QLabel创建一个简单的标签小部件,作为我们的第一个自定义小部件。一个自定义小部件集合可以有多个自定义小部件。
New->Other Project->Qt Custom Designer Widget,步骤如下:



工程目录:

展开Project Explorer视图并打开mylabel.h文件。我们将修改内容以扩展功能。在自定义小部件类名之前添加QDESIGNER_WIDGET_EXPORT宏,以确保在动态链接库(dynamic-link library:DLL)或共享库中正确导出该类。你的自定义小部件可能在没有此宏的情况下工作,但添加此宏是一个很好的做法。插入宏后,必须将#include添加到头文件中。mylabel.h修改如下:

#ifndef MYLABEL_H
#define MYLABEL_H
#include
#include
class QDESIGNER_WIDGET_EXPORT MyLabel: public QLabel
Q_OBJECT
Q_PROPERTY(bool multiLine READ isMultiLine WRITE setMultiLine)
Q_PROPERTY(Qt::GlobalColor color READ getColor WRITE setColor)
private:
bool m_isMultiLine = false;
Qt::GlobalColor m_color = Qt::GlobalColor::black;
public:
MyLabel(QWidget *parent = 0);
void setMultiLine(bool isMultiLine);
bool isMultiLine() const return m_isMultiLine;
void setColor(Qt::GlobalColor color);
Qt::GlobalColor getColor() return m_color;
;
#endif

mylabel.cpp代码如下:

#include "mylabel.h"
MyLabel::MyLabel(QWidget *parent): QLabel(parent)
void MyLabel::setMultiLine(bool isMultiLine) m_isMultiLine = isMultiLine;
void MyLabel::setColor(Qt::GlobalColor color) m_color = color;


注:
在某些平台上,构建系统可能会删除Qt Designer模块创建新小部件所需的符号,使其无法使用。使用QDESIGNER_WIDGET_EXPORT宏可确保符号保留在这些平台上。这在创建跨平台库时非常重要。在其他平台上没有副作用。


mylabelplugin.h

#ifndef MYLABELPLUGIN_H
#define MYLABELPLUGIN_H
#include
class MyLabelPlugin : public QObject, public QDesignerCustomWidgetInterface
Q_OBJECT
Q_INTERFACES(QDesignerCustomWidgetInterface)
public:
MyLabelPlugin(QObject *parent = 0);

bool isContainer() const;
bool isInitialized() const;
QIcon icon() const;
QString domXml() const;
QString group() const;
QString includeFile() const;
QString name() const;
QString toolTip() const;
QString whatsThis() const;
QWidget *createWidget(QWidget *parent);
void initialize(QDesignerFormEditorInterface *core);
private:
bool m_initialized;
;
#endif

可以看到MyLabelPlugin类继承自类QDesignerCustomWidgetInterface,这个类允许Qt Designer去访问和创建自定义小部件。
请注意,你得更改头文件如下,以避免depressed warnings,如下:

修改为如下,则不报depressed warnings:

#include

mylabelplugin.cpp

#include "mylabel.h"
#include "mylabelplugin.h"
#include
MyLabelPlugin::MyLabelPlugin(QObject *parent): QObject(parent)
m_initialized = false;

void MyLabelPlugin::initialize(QDesignerFormEditorInterface * /* core */)
if (m_initialized)
return;
// Add extension registrations, etc. here
m_initialized = true;

bool MyLabelPlugin::isInitialized() const return m_initialized;
QWidget *MyLabelPlugin::createWidget(QWidget *parent) return new MyLabel(parent);
QString MyLabelPlugin::name() const return QLatin1String("MyLabel");
QString MyLabelPlugin::group() const return QLatin1String("");
QIcon MyLabelPlugin::icon() const return QIcon();
QString MyLabelPlugin::toolTip() const return QLatin1String("");
QString MyLabelPlugin::whatsThis() const return QLatin1String("");
bool MyLabelPlugin::isContainer() const return false;
QString MyLabelPlugin::domXml() const
return QLatin1String("\\n\\n");

QString MyLabelPlugin::includeFile() const return QLatin1String("mylabel.h");
#if QT_VERSION < 0x050000
Q_EXPORT_PLUGIN2(mylabelplugin, MyLabelPlugin)
#endif

请不要删除生成的函数。你可以给name()、group()、icon()指定值。注意&#xff0c;如果你不给icon()指定值&#xff0c;Qt Designer会使用默认的Qt icon。

你可以看到&#xff0c;isContainer()返回false在MyLabel&#xff0c;MyFrame返回true。因为MyLabel不是设计用来作为其他小部件的容器的&#xff0c;而MyFrame在创建时就勾选了“The widget is a container”。
Qt Designer调用createWidget()去生成一个MyLabelMyFrame的实例。

我们指定myframeplugin.cpp中的group()值&#xff0c;如下&#xff1a;

QString MyFramePlugin::group() const return QLatin1String("My Container");

要创建具有自定义几何体或任何其他属性的小部件&#xff0c;则在domXML()方法中指定这些属性。该函数返回可扩展标记语言&#xff08;XML&#xff09;片段&#xff0c;小部件工厂(the widget factory)使用该片段创建具有定义属性的自定义小部件。
让我们指定MyLable宽&#61;100px&#xff0c;高&#61;16px&#xff0c;如下&#xff1a;

QString MyLabelPlugin::domXml() const
return "\\n"
"\\n"
"\\n"
"<rect>\\n"
"<x>0x>\\n"
"<y>0y>\\n"
"<width>100width>\\n"
"<height>16height>\\n"
"rect>\\n"
"property>\\n"
"\\n"
"<string>MyLabelstring>\\n"
"property>\\n"
"widget>\\n"
"ui>\\n";

现在我们看看MyWidgets.pro文件&#xff0c;如下。
它包含qmake所需的所有信息去构建自定义小部件集合库。

#MyWidgets.pro
CONFIG &#43;&#61; plugin debug_and_release
TARGET &#61; $$qtLibraryTarget(mylabelplugin)
TEMPLATE &#61; lib
HEADERS &#61; mylabelplugin.h
SOURCES &#61; mylabelplugin.cpp
RESOURCES &#61; icons.qrc
LIBS &#43;&#61; -L.
greaterThan(QT_MAJOR_VERSION, 4)
QT &#43;&#61; designer
else
CONFIG &#43;&#61; designer

target.path &#61; $$[QT_INSTALL_PLUGINS]/designer
INSTALLS &#43;&#61; target
include(mylabel.pri)

可以看到&#xff0c;这个工程是一个库类型&#xff0c;并且被配置用作一个插件。

现在&#xff0c;让我们运行qmake并在Release模式下构建这个库。

Build后&#xff0c;在项目所在目录生成如下文件夹&#xff1a;

在Windows平台上&#xff0c;可以手动将新生成的文件夹里的release目录下的mywidgetcollectionplugin.dll复制到D:\\Qt\\6.0.0\\mingw81_64\\plugins\\designer路径下。这个路径及文件扩展名依不同操作系统而异。如果不做这样的拷贝操作&#xff0c;就无法在designer.exe窗口看到我们自定义的插件。

此时&#xff0c;我们已经创建了我们自定义的插件。
现在&#xff0c;在D:\\Qt\\6.0.0\\mingw81_64\\bin目录下找到designer.exe&#xff0c;双击打开。
可以看到我们自定义的部件&#xff1a;

单击“创建”按钮&#xff0c;将MyLabel拖到MyFrame里面。

你还可以在属性编辑器中看到创建的MyLabel的属性&#xff1a;自定义QLabel下的multiLine、color属性。

你现在已经成功创建了你的自定义部件&#xff0c;并拥有新的属性。你也可以通过组合不同的部件创建更复杂的部件。



你还可以在以下Qt文档链接中找到带有示例的详细说明&#xff1a;
https://doc.qt.io/qt-6/designer-creating-custom-widgets.html



创建Qt样式表和自定义主题

Qt提供了几种定制UI外观的方法。Qt样式表(Qt Style Sheet)是在不进行复杂编码的情况下改变小部件外观的最简单方法之一。Qt样式表语法与超文本标记语言(html)/级联样式表(CSS)语法相同。样式表由一系列样式规则组成。样式规则由选择器和声明组成。选择器指定将受样式规则影响的小部件&#xff0c;声明指定小部件的属性。样式规则的声明部分是一个属性列表&#xff0c;作为键值对&#xff0c;包含在中&#xff0c;用分号分隔。

让我们来看一个简单的QPushButton样式表语法&#xff1a;

QPushButtoncolor:green; background-color:

推荐阅读
  • JavaScript 基础语法指南
    本文详细介绍了 JavaScript 的基础语法,包括变量、数据类型、运算符、语句和函数等内容,旨在为初学者提供全面的入门指导。 ... [详细]
  • Python处理Word文档的高效技巧
    本文详细介绍了如何使用Python处理Word文档,涵盖从基础操作到高级功能的各种技巧。我们将探讨如何生成文档、定义样式、提取表格数据以及处理超链接和图片等内容。 ... [详细]
  • 编写了几个500行左右代码的程序,但基本上解决问题还是面向过程的思维,如何从问题中抽象出类,形成类的划分和设计,从而用面向对象的思维解决问题?有这方面的入门好书吗?最好是结合几个具体的案例分析的 ... [详细]
  • Qt QTableView 内嵌控件的实现方法
    本文详细介绍了在 Qt QTableView 中嵌入控件的多种方法,包括使用 QItemDelegate、setIndexWidget 和 setIndexWidget 结合布局管理器。每种方法都有其适用场景和优缺点。 ... [详细]
  • 本文介绍如何从字符串中移除大写、小写、特殊、数字和非数字字符,并提供了多种编程语言的实现示例。 ... [详细]
  • 使用Powershell Studio快速构建GUI应用程序
    本文介绍了如何利用Powershell Studio创建功能强大的可视化界面。相较于传统的开发工具,Powershell Studio提供了更为简便和高效的开发体验,尤其适合需要快速构建图形用户界面(GUI)的场景。 ... [详细]
  • 本文介绍了如何在iOS应用中自定义导航栏按钮,包括使用普通按钮和图片生成导航条专用按钮的方法。同时,探讨了在不同版本的iOS系统中实现多按钮布局的技术方案。 ... [详细]
  • 本文详细介绍了C语言的起源、发展及其标准化过程,涵盖了从早期的BCPL和B语言到现代C语言的演变,并探讨了其在操作系统和跨平台编程中的重要地位。 ... [详细]
  • 对象自省自省在计算机编程领域里,是指在运行时判断一个对象的类型和能力。dir能够返回一个列表,列举了一个对象所拥有的属性和方法。my_list[ ... [详细]
  • 在创建新的Android项目时,您可能会遇到aapt错误,提示无法打开libstdc++.so.6共享对象文件。本文将探讨该问题的原因及解决方案。 ... [详细]
  • CentOS 6.5 上安装 MySQL 5.7.23 的详细步骤
    本文详细介绍如何在 CentOS 6.5 系统上成功安装 MySQL 5.7.23,包括卸载旧版本、下载安装包、配置文件修改及启动服务等关键步骤。 ... [详细]
  • 本文详细介绍了如何使用 HTML 和 CSS 创建一个功能齐全的联系我们表单,包括布局和样式设计。 ... [详细]
  • 本文介绍如何在C#中将GridView控件的内容保存为图片文件。通过代码示例,详细说明了创建位图、绘制图形并保存图像的步骤。 ... [详细]
  • 当unique验证运到图片上传时
    2019独角兽企业重金招聘Python工程师标准model:public$imageFile;publicfunctionrules(){return[[[na ... [详细]
  • springMVC JRS303验证 ... [详细]
author-avatar
男人--沉默底线
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有